using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace StupidSpaceThing
{
	internal class Player : Unit
	{
		private const double changeFactionLag = 1000;
		private double startChangeFaction;
		private Faction changeFaction;
		public bool CanChangeFaction = true;
		public bool CanShoot = true;
		public bool CanControlMines = false;
		public bool Died = false;

		public Player(Vector3 position)
			: base(new PlayerEntity(position)) {
			massModifier = 70;
			turnSpeed = 1;
		}

		public void ChangeFaction(Faction newFaction, RealGameTime gameTime) {
			if( !CanChangeFaction ) {
				return;
			}
			if( !newFaction.Defeated ) {
				changeFaction = newFaction;
			}
			if( Faction != Faction.None ) {
				Faction.Remove(this);
				Faction.None.Add(this);
			}
			SoundSystem.PlayCue("changecolor", Game1.Listener, AudioEmitter);
			if( !newFaction.Defeated ) {
				startChangeFaction = gameTime.TotalRealGameTime.TotalMilliseconds;
			}
		}

		public void ControlMines(float force) {
			if( !CanControlMines ) return;
			foreach( FactionEntity fe in Faction.FactionEntities ) {
				if( fe is Mine ) {
					float distance = Vector3.Distance(fe.Position, Position);
					if( distance < 35 ) {
						(fe as Mine).ApplyForce(Vector2.Normalize(Position2D - fe.Position2D) * force * 100, true);
					}
				}
			}
		}

		public void ControlOneMine(float force) {
			if( !CanControlMines ) return;
			FactionEntity closest = null;
			float closestDistance = float.MaxValue;
			foreach( FactionEntity fe in Faction.FactionEntities ){
				if( fe is Mine || fe is JellyFish ) {
					float distance = Vector3.Distance(fe.Position, Position);
					if( fe is Mine ){
						if( distance < closestDistance && distance < 35 ) {
							closest = fe;
							closestDistance = distance;
						} 
					} else{
						if( distance < closestDistance && distance < 65 ) {
							closest = fe;
							closestDistance = distance;
						}
					}
				}
			}
			if( closest != null ) {
				float forceMultiplyer = 1;
				if( closest is JellyFish ) {
					forceMultiplyer = -1;
				}
				(closest as Unit).ApplyForce(Vector2.Normalize(Position2D - closest.Position2D) * force * forceMultiplyer * 300, true);
			}
		}

		public override void Update(RealGameTime gameTime) {
			if( changeFaction != null && startChangeFaction + changeFactionLag < gameTime.TotalRealGameTime.TotalMilliseconds ) {
				Faction.Remove(this);
				changeFaction.Add(this);
				changeFaction = null;
			}

			Color lifeIndicator = new Color((byte)(MathHelper.Lerp(0, 255, 1 - Entity.Life / 100.0f)), (byte)(MathHelper.Lerp(0, 255, Entity.Life / 100.0f)), 0);
			//Bullets.Fire(new Bullet(lifeIndicator, this, Vector3.Down, 0, gameTime, false));
			base.Update(gameTime);
		}

		public override void Die() {
			if( !Died ) {
				GuideSystem.ShowPriority(new TextGuide(getDeathLine(), Game1.SpriteFont, TextAlign.Both, 1, Color.White, 4000, delegate() {
					Game1.Game.Reset();
				}));
				Entity.ScaleFactor = 100000;
				Entity.Heal(100);
				Entity.Armor = 10000;
				Entity.Dead = false;
				Died = true;
			}
		}

		private string getDeathLine(){
			string[] lines = {
				//"Try again. Watch out this time, you don't have much energy!",
				"Come on, we don't have unlimited ressources you know",
				"Dammit, get your act together!",
				"Stop fooling around and do your job!"
			};
			string[] level1_lines = {
				"Dammit. Next time try scouting ahead with the right stick",
				"Try again. Remember to change color when approaching an enemy!"
			};
			string[] level2_lines = {
				"Get your act together agent!",
				"Try again, maybe try saving some logic bombs for later"
			};
			string[] level3_lines = {
				"Try again, and go check the data entries first!"
			};
			string[] curLines = null;
			switch( Game1.Level ) {
				case 1:
					curLines = combine(level1_lines, lines);
					break;
				case 2:
					curLines = combine(level2_lines, lines);
					break;
				case 3:
					curLines = combine(level3_lines, lines);
					break;
				default:
					curLines = lines;
					break;
			}			
			return curLines[Game1.Random.Next(0, curLines.Length)];
		}

		private string[] combine(string[] lines1, string[] lines2) {
			List<string> newLines = new List<string>();
			foreach(string s in lines1){ newLines.Add(s); }
			foreach(string s in lines2){ newLines.Add(s); }
			return newLines.ToArray();
		}
	}
}
